﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using SerienNewsReader.Model;

namespace SerienNewsReader
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        /// <summary>
        /// Contains all series
        /// </summary>
        private ObservableCollection<RSSFeed> serien = default(ObservableCollection<RSSFeed>);

        /// <summary>
        /// Contains all tv movies
        /// </summary>
        private ObservableCollection<RSSFeed> tvMovies = default(ObservableCollection<RSSFeed>);

        /// <summary>
        /// The last applyed filter result
        /// </summary>
        private IEnumerable<RSSFeed> previewsViewSeries = null;

        private IEnumerable<RSSFeed> previewsViewTvMovies = null;

        /// <summary>
        /// The title for the last applyed filter
        /// </summary>
        private string previewsTitle = windowTitle;

        /// <summary>
        /// List of all serises that are stored in the settings file
        /// </summary>
        private List<string> titles = new List<string>();

        /// <summary>
        /// Default title of the main window
        /// </summary>
        private const string windowTitle = "Serien News Reader";

        private ViewModel.Series serienViewModle = new ViewModel.Series();

        /// <summary>
        /// Initializes a new instance of MainWindow class
        /// </summary>
        public MainWindow()
        {
            InitializeComponent();
            this.CustiomInitialize();
            this.LoadSerien();
            this.BuildFilterMenu();
        }

        /// <summary>
        /// Initializes needed objects or members for this class and subscribs for events
        /// </summary>
        private void CustiomInitialize()
        {
            this.tvMovies = serienViewModle.TvMovies;
            this.serien = serienViewModle.Serien;
            this.previewsViewSeries = serienViewModle.Serien;
            this.previewsViewTvMovies = this.tvMovies;
            this.dataGridSerien.ItemsSource = this.serien;
            this.dataGridTvMovies.ItemsSource = this.tvMovies;

            this.tabControl.SelectionChanged += new SelectionChangedEventHandler(tabControl_SelectionChanged);
        }

        /// <summary>
        /// Clears the search text box when the tab page was changed
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void tabControl_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (!String.IsNullOrEmpty(this.textBoxFilter.Text))
            {
                this.textBoxFilter.Clear();
            }
        }

        /// <summary>
        /// Triggers the loading of all series
        /// </summary>
        private void LoadSerien()
        {

            serienViewModle.DownloadCompleted += new ViewModel.Series.DownloadCompletedDelegate(OnDownloadCompleted);
            SerienNewsReader.config.Default.SettingsSaving += new System.Configuration.SettingsSavingEventHandler(Default_SettingsSaving); 
        }

        /// <summary>
        /// When the download of all series is finished the filter menu will be enabled
        /// </summary>
        /// <param name="sender">Object that sends the event</param>
        /// <param name="e">Event aruments</param>
        void OnDownloadCompleted(object sender, EventArgs e)
        {
            this.menuItemFilters.IsEnabled = true;
            this.progressBarDownload.Visibility = System.Windows.Visibility.Hidden;
        }

        /// <summary>
        /// Updates the menue item filter when the settings where changed
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void Default_SettingsSaving(object sender, System.ComponentModel.CancelEventArgs e)
        {
            this.BuildFilterMenu();
        }

        /// <summary>
        /// Generates all entries for the Filter menue
        /// </summary>
        private void BuildFilterMenu()
        {
            if (this.menuItemFilters.Items.Count > 0)
            {
                this.menuItemFilters.Items.Clear();
            }
            MenuItem allSeries = new MenuItem();
            allSeries.Header = "All Series";

            if (!String.IsNullOrEmpty(SerienNewsReader.config.Default.Series))
            {
                string[] entries = SerienNewsReader.config.Default.Series.Split(';');
                if (entries.Length > 0)
                {
                    foreach (string entry in entries)
                    {
                        if (!string.IsNullOrEmpty(entry))
                        {
                            MenuItem item = new MenuItem();
                            item.Header = entry;
                            item.Click += new RoutedEventHandler(this.FilterItem_Click);
                            this.menuItemFilters.Items.Add(item);
                            this.titles.Add(entry);
                        }
                    }
                }
                MenuItem allFilters = new MenuItem();
                allFilters.Header = "All my series";
                allFilters.Click +=new RoutedEventHandler(allFilters_Click);
                allFilters.IsEnabled = true;
                this.menuItemFilters.Items.Add(new Separator());
                this.menuItemFilters.Items.Add(allFilters);
            }
        }

        /// <summary>
        /// Applays a filter that shows all series that are stored in the settings
        /// </summary>
        /// <param name="sender">Object that sends the event</param>
        /// <param name="e">Event arguements</param>
        void allFilters_Click(object sender, RoutedEventArgs e)
        {
            this.previewsViewSeries = this.dataGridSerien.ItemsSource as IEnumerable<RSSFeed>;
            this.previewsTitle = this.NewsReader.Title;
            this.ClearSelection();
            List<RSSFeed> allSeries = new List<RSSFeed>();

            foreach (string title in this.titles)
            {
                allSeries.AddRange(this.serien.Where(x => x.Title.ToLower().Contains(title.ToLower())));
            }

            this.dataGridSerien.ItemsSource = allSeries.OrderBy(x => x.Title);
            this.Title = windowTitle + " - All series";
        }

        /// <summary>
        /// Sets the filter to the selected item
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void FilterItem_Click(object sender, RoutedEventArgs e)
        {
            ClearSelection();

            MenuItem item = null;
            if (sender is MenuItem)
            {
                item = sender as MenuItem;
            }
            else
            {
                return;
            }

            if (item != null)
            {
                item.IsChecked = true;
                this.ApplyFilter(this.PrepareAkademikDegreeFilter(item.Header as string));
            }
            else
            {
                return;
            }
        }

        /// <summary>
        /// A parser for akademik degrees that are contained in a title
        /// </summary>
        /// <param name="title">Title of the serie that needs to be checked and prepared</param>
        /// <returns>Manipulated title of the serie</returns>
        private string PrepareAkademikDegreeFilter(string title)
        {
            string newTitle = title;
            if (title.ToLower().Contains("dr."))
            {
                newTitle = title.Replace(" ", "");
                newTitle = newTitle.Replace('.', ' ');
            }
            return newTitle;
        }

        /// <summary>
        /// Clears all currently selected items
        /// </summary>
        private void ClearSelection()
        {
            foreach (var entry in this.menuItemFilters.Items)
            {
                MenuItem menuItem = null;
                if (entry is MenuItem)
                {
                    menuItem = entry as MenuItem;
                }
                if (menuItem != null)
                {
                    if (menuItem.IsChecked)
                    {
                        menuItem.IsChecked = false;
                    }
                }
            }
        }

        /// <summary>
        /// Opens the Hyperlink with the default browser
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnHyperlink_Click(object sender, RoutedEventArgs e)
        {
            Process.Start((e.Source as Hyperlink).NavigateUri.ToString());
        }

        /// <summary>
        /// Applies the filter depending on the words that are tipped into the text box
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void textBoxFilter_TextChanged(object sender, TextChangedEventArgs e)
        {
            this.ClearSelection();
            this.ApplyFilter(this.textBoxFilter.Text);
        }

        /// <summary>
        /// Filters the list with the given filter criterian
        /// </summary>
        /// <param name="filter">the filter criterian</param>
        private void ApplyFilter(String filter)
        {
            if (String.IsNullOrEmpty(filter))
            {
                this.dataGridSerien.ItemsSource = this.serien;
                this.NewsReader.Title = windowTitle;
            }
            else
            {
                this.previewsTitle = this.NewsReader.Title;
                if (filter.Contains('.'))
                {
                    filter = filter.Replace('.', ' ');
                }

                this.NewsReader.Title = windowTitle + " - " + filter;
                filter = filter.ToLower();

                if (this.tabItemSerises.IsSelected)
                {
                    this.previewsViewSeries = this.dataGridSerien.ItemsSource as IEnumerable<RSSFeed>;
                    this.dataGridSerien.ItemsSource = this.serien.Where(x => x.Title.ToLower().Contains(filter)).OrderBy(
                        x => x.Title); 
                }
                else if (this.tabItemTvMovies.IsSelected)
                {
                    this.previewsViewTvMovies = this.dataGridTvMovies.ItemsSource as IEnumerable<RSSFeed>;
                    this.dataGridTvMovies.ItemsSource = this.tvMovies.Where(x => x.Title.ToLower().Contains(filter)).OrderBy(
                        x => x.Title);
                }
            }
        }

        /// <summary>
        /// Shows the Options dialog
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void menuItemOptions_Click(object sender, RoutedEventArgs e)
        {
            OptionsDialog dialog = new OptionsDialog();
            dialog.ShowDialog();
        }

        /// <summary>
        /// Shows the list of all series
        /// </summary>
        /// <param name="sender">Object that sends the event</param>
        /// <param name="e">Event arguments</param>
        private void buttonBack_Click(object sender, RoutedEventArgs e)
        {
            this.dataGridSerien.ItemsSource = this.previewsViewSeries;
            this.NewsReader.Title = this.previewsTitle;
            foreach (var item in this.menuItemFilters.Items)
            {
                if (item is MenuItem)
                {
                    if (((MenuItem)item).IsChecked)
                    {
                        ((MenuItem)item).IsChecked = false;
                    }
                }
            }
        }
    }
}